package com.wht.sip.core.transmit.message;

import cn.hutool.core.collection.CollUtil;
import com.wht.sip.config.SipConfig;
import com.wht.sip.core.context.SipProcessorContext;
import com.wht.sip.core.transmit.SIPSender;
import com.wht.sip.core.transmit.model.Gb28181Sdp;
import com.wht.sip.utils.IpPortUtil;
import com.wht.sip.utils.SipUtils;
import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.message.SIPResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Managed;

import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.List;

/**
 * @author by HaiTao.Wang on 2025/9/15.
 */
@Slf4j
@Managed
public class InviteMessageProcessor extends SipRequestProcessorHandle implements SipMessageProcessor {

    @Inject
    private SipConfig sipConfig;

    @Inject
    private SIPSender sipSender;

    @Init
    public void init() {

        SipProcessorContext.requestProcessor.put("INVITE", this);
        SipProcessorContext.responseProcessor.put("INVITE", this);
    }

    /**
     * 处理注册请求
     *
     * @param event 请求事件
     */
    @SneakyThrows
    @Override
    public void processRequest(RequestEvent event) {

        log.info("request-INVITE:");

    }

    /**
     * 处理响应
     *
     * @param responseEvent 响应事件
     */
    @Override
    public void processResponse(ResponseEvent responseEvent) {
        log.debug("response-INVITE 接收到消息：{}", responseEvent.getResponse());
        try {
            SIPResponse response = (SIPResponse) responseEvent.getResponse();
            int statusCode = response.getStatusCode();
            // trying不会回复
            if (statusCode == Response.TRYING) {
                log.info("尝试..");
            }

            // 成功响应
            // 下发ack
            if (statusCode == Response.OK) {
                ResponseEventExt event = (ResponseEventExt) responseEvent;

                String contentString = new String(response.getRawContent());
                Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString);
                SessionDescription sdp = gb28181Sdp.getBaseSdb();
                SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), IpPortUtil.concatenateIpAndPort(event.getRemoteIpAddress(), String.valueOf(event.getRemotePort())));
                Request reqAck = createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);

                log.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
                sipSender.transmitRequest(reqAck);
            }
        } catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
            log.info("[点播回复ACK]，异常：", e);
        }
    }

    /**
     * 创建ack请求
     *
     * @param localIp     本地ip
     * @param sipUri      sip uri
     * @param sipResponse sip响应
     * @return ack请求
     * @throws ParseException           解析异常
     * @throws InvalidArgumentException 无效参数异常
     * @throws PeerUnavailableException 节点不可用异常
     */
    private Request createAckRequest(String localIp, SipURI sipUri, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {

        // via
        List<ViaHeader> viaHeaders = CollUtil.newArrayList();
        ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
        viaHeaders.add(viaHeader);

        //Forwards
        MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);

        //ceq
        CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);

        Request request = SipFactory.getInstance().createMessageFactory().createRequest(sipUri, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);

        Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(localIp, String.valueOf(sipConfig.getPort()))));
        request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));

        request.addHeader(SipUtils.createUserAgentHeader());

        return request;
    }

}
